﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;

namespace CommonSearchModule.SearchCourseRequirement
{
    /// <summary>
    /// 建立Res_Item表对象的索引
    /// </summary>
    public class CreateIndexFile
    {
        #region Properties

        private readonly string connString = ConfigurationManager.AppSettings["connString"];
        private readonly string connString_LiveCourse = ConfigurationManager.AppSettings["connString_LiveCourse"];

        /// <summary>
        /// 配置文件路径
        /// </summary>
        public string ConfigPath { get; private set; }

        /// <summary>
        /// 索引文件存放总目录
        /// </summary>
        public string DocumentsPath { get; private set; }

        /// <summary>
        /// 要生成的索引文件的目录
        /// </summary>
        public string CreateSearchIndexPath { get; private set; }

        #endregion Properties

        #region Constructors

        public CreateIndexFile()
        {
            this.DocumentsPath = IndexDocumentsConfig.GetIndexDocumentPath(SearchModule.Fudao);
            this.ConfigPath = Path.Combine(this.DocumentsPath, "Config.ini");
            this.CreateSearchIndexPath = GetCreatePath();
        }

        #endregion Constructors

        #region Public Methods

        public void Create()
        {
            //创建分析器
            StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
            IndexWriter writer = new IndexWriter(CreateSearchIndexPath, standardAnalyzer, true);
            Stopwatch watch = new Stopwatch();
            watch.Start();
            StringBuilder sb;

            #region 学生

            using (SqlConnection conn = new SqlConnection(connString))
            {
                sb = new StringBuilder();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                sb.Append(@" 
SELECT 
a.ID as ItemID, 
a.Title as Name, 
a.PublishDate as PackageTime,
a.Remark as Info, 
CategoryName='',
c.Name+'|'+d.Name as PropertyName

FROM dbo.IC_Student_CourseRequirement a
inner JOIN IC_Course_Category_R  b ON a.ID = b.ID 
             and IsValid=1                                           
inner Join dbo.Common_BasePropValue c On b.GradeID=c.VID AND c.PID=1
inner Join dbo.Common_BasePropValue d On b.SubjectID=d.VID AND d.PID=2
");
                comm.CommandText = sb.ToString();
                conn.Open();
                SqlDataReader reader = comm.ExecuteReader();

                int rowCount = 1;
                try
                {
                    while (reader.Read())
                    {
                        Search_Entity entity = new Search_Entity();
                        entity.ID = reader["ItemID"].ToString();
                        entity.Name = reader["Name"].ToString();
                        entity.Info = reader["Info"].ToString();
                        entity.CategoryName = reader["CategoryName"].ToString();
                        entity.PackageTime = reader["PackageTime"].ToString();
                        entity.PropertyName = reader["PropertyName"].ToString();

                        //添加到索引
                        Document doc = InitDocument(entity);
                        writer.AddDocument(doc);

                        Console.SetCursorPosition(0, 0);
                        Console.WriteLine("执行次数：" + rowCount++.ToString());
                        Console.WriteLine("执行时间：" + watch.Elapsed.ToString());
                    }
                }
                finally
                {
                    reader.Close();
                }
            }

            #endregion 学生

            #region 老师


            //直播课程
            using (SqlConnection conn = new SqlConnection(connString))
            {
                #region 小班

                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = @"
SELECT 
a.ID as ItemID, 
a.Title as Name, 
a.PublishDate as PackageTime,
a.Remark as Info, 
CategoryName='',
c.Name+'|'+d.Name as PropertyName

FROM dbo.IC_Teacher_CourseRequirement a
inner JOIN IC_Course_Category_R  b ON a.ID = b.ID 
             and IsValid=1                                           
inner Join dbo.Common_BasePropValue c On b.GradeID=c.VID AND c.PID=1
inner Join dbo.Common_BasePropValue d On b.SubjectID=d.VID AND d.PID=2

";
                conn.Open();
                SqlDataReader reader = comm.ExecuteReader();

                int rowCount = 1;
                try
                {
                    while (reader.Read())
                    {
                        Search_Entity entity = new Search_Entity();
                        entity.ID = reader["ItemID"].ToString();
                        entity.Name = reader["Name"].ToString();
                        entity.Info = reader["Info"].ToString();
                        entity.CategoryName = reader["CategoryName"].ToString();
                        entity.PackageTime = reader["PackageTime"].ToString();
                        entity.PropertyName = reader["PropertyName"].ToString();

                        //添加到索引
                        Document doc = InitDocument(entity);
                        writer.AddDocument(doc);

                        Console.SetCursorPosition(0, 0);
                        Console.WriteLine("执行次数：" + rowCount++.ToString());
                        Console.WriteLine("执行时间：" + watch.Elapsed.ToString());
                    }
                }
                finally
                {
                    reader.Close();
                }

                #endregion 小班


            }


            #endregion 老师

            writer.Optimize();
            writer.Close();

            TimeSpan _RunTime = new TimeSpan(DateTime.Now.Ticks);
            TimeSpan _RunTime2 = new TimeSpan(DateTime.Now.AddDays(-2).Ticks);
            TimeSpan ss = _RunTime.Subtract(_RunTime2);
            Console.WriteLine(ss.Hours);

            SetCreatePath();
        }

        #endregion Public Methods

        #region Private Methods

        /// <summary>
        /// 初始化Document流中的字段field
        /// Field.Index 	Field.Store 	说明
        /// TOKENIZED（分词） 	YES 	被分词索引且存储
        /// TOKENIZED 	        NO 	被分词索引但不存储
        /// NO 	                YES 	这是不克不及被搜刮的，它只是被搜刮内容的从属物。如URL等
        /// UN_TOKENIZED 	    YES/NO 	不被分词，它作为一个整体被搜刮，搜一项目组是搜不出来的
        /// NO 	                NO 	没有这种用法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private Document InitDocument(Search_Entity entity)
        {
            Document doc = new Document();

            doc.Add(new Field(FieldKeys.ID, entity.ID.ToString(), Field.Store.YES, Field.Index.TOKENIZED));
            if (!string.IsNullOrEmpty(entity.Name))
                doc.Add(new Field(FieldKeys.Name, entity.Name, Field.Store.YES, Field.Index.TOKENIZED));
            if (!string.IsNullOrEmpty(entity.Info))
                doc.Add(new Field(FieldKeys.Info, entity.Info , Field.Store.YES, Field.Index.TOKENIZED));
            if (!string.IsNullOrEmpty(entity.CategoryName))
                doc.Add(new Field(FieldKeys.CategoryName, entity.CategoryName, Field.Store.YES, Field.Index.TOKENIZED));
            if (!string.IsNullOrEmpty(entity.PropertyName))
                doc.Add(new Field(FieldKeys.PropertyName, entity.PropertyName.TrimEnd(new char[] { '|' }), Field.Store.YES, Field.Index.TOKENIZED));
            if (!string.IsNullOrEmpty(entity.PackageTime))
                doc.Add(new Field(FieldKeys.PackageTime, entity.PackageTime, Field.Store.YES, Field.Index.TOKENIZED));

            doc.Add(new Field(FieldKeys.SearchKey, "key", Field.Store.NO, Field.Index.UN_TOKENIZED));

            return doc;
        }

        /// <summary>
        /// 获取将要生成索引的文件目录
        /// </summary>
        /// <returns></returns>
        private string GetCreatePath()
        {
            string createPath = "";

            string path1 = Path.Combine(DocumentsPath, "1");//文件夾１
            string path2 = Path.Combine(DocumentsPath, "2");//文件夾２

            if (!System.IO.Directory.Exists(DocumentsPath)) System.IO.Directory.CreateDirectory(DocumentsPath);

            if (File.Exists(ConfigPath))
            {
                StringBuilder sbPath = new StringBuilder(500);
                GetPrivateProfileString("Index", "Path", "", sbPath, 500, ConfigPath);

                string strPath = sbPath.ToString();
                if (strPath.IndexOf("1") != -1)
                {
                    createPath = path2;
                }
                else
                {
                    createPath = path1;
                }
            }
            else
            {
                createPath = path1;
                WritePrivateProfileString("Index", "Path", createPath, ConfigPath);
            }
            if (!System.IO.Directory.Exists(createPath)) System.IO.Directory.CreateDirectory(createPath);

            return createPath;
        }

        private void SetCreatePath()
        {
            WritePrivateProfileString("Index", "Path", CreateSearchIndexPath, ConfigPath);
        }

        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        //修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 属性一起使用。在这种情况下，还必须将方法声明为 static

        #endregion Private Methods
    }
}